from django.db import models
from backend.models import Staff
from core.models import Member
import datetime
import os
import uuid

class Category(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

# thanks to http://stackoverflow.com/questions/2673647/enforce-unique-upload-file-names-using-django
def uuid_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('item-images', filename)

class DessertItem(models.Model):
    name = models.CharField(max_length=100)
    detail = models.TextField()
    pic = models.ImageField(upload_to=uuid_file_path)
    category = models.ForeignKey(Category, related_name='items', null=True)

    def get_stock(self):
        year, week, weekday = datetime.datetime.today().isocalendar()
        res = PlanEntry.objects.filter(item=self, plan__year__exact=year, plan__week=week, plan__weekday=weekday)
        if res:
            return res[0].stock
        else:
            return 0

    def set_stock(self, updated_stock):
        year, week, weekday = datetime.datetime.today().isocalendar()
        res = PlanEntry.objects.filter(item=self, plan__year__exact=year, plan__week=week, plan__weekday=weekday)
        if res:
            res[0].stock = updated_stock
            res[0].save()

    def get_price(self):
        year, week, weekday = datetime.datetime.today().isocalendar()
        res = PlanEntry.objects.filter(item=self, plan__year__exact=year, plan__week=week, plan__weekday=weekday)
        if res:
            return res[0].price
        else:
            return 'NA'

    stock = property(get_stock, set_stock)
    price = property(get_price)

    def __unicode__(self):
        return self.name

class Sale(models.Model):
    customer = models.ForeignKey(Member)
    is_paid = models.BooleanField(default=False)
    paid_time = models.DateTimeField(null=True)
    discount_rate = models.FloatField()
    # fields to deal with reservation
    is_reservation = models.BooleanField(default=False)
    get_day = models.DateField(null=True)
    is_paid_off = models.BooleanField(default=False)
    paid_off_time = models.DateTimeField(null=True)

    items = models.ManyToManyField(DessertItem, through='SaleEntry')

    def total(self):
        total = 0.0
        for entry in self.entries.all():
            total += entry.total()
        return total * self.discount_rate

    def first_round_payment(self):
        total = self.total()
        if self.is_reservation:
            total = round(total/2, 2)
        return total

    def second_round_payment(self):
        return self.total() - self.first_round_payment()

    def __unicode__(self):
        return "%s's sale|%s" % (self.customer, self.paid_time)

    @staticmethod
    def recent_items(customer, from_reservation):
        sales = customer.sale_set.filter(is_paid=True, is_reservation=from_reservation).order_by('-paid_time')[:5]
        items = []
        [items.extend((entry.item for entry in s.entries.all())) for s in sales]
        items = list(set(items))
        return items

class SaleEntry(models.Model):
    sale = models.ForeignKey(Sale, related_name='entries')
    item = models.ForeignKey(DessertItem)
    quantity = models.IntegerField()
    price = models.FloatField()

    def total(self):
        return self.price * self.quantity

    def __unicode__(self):
        return 'sale entry of %s(%s)' % (self.item, self.quantity)

class WeekdayPlan(models.Model):
    year = models.IntegerField()
    week = models.IntegerField()
    weekday = models.IntegerField()
    item = models.ManyToManyField(DessertItem, through='PlanEntry')

    def __unicode__(self):
        return 'Plan of week no.%s, %s by %s' % (self.week, self.year, self.creator)

class PlanEntry(models.Model):
    creator = models.ForeignKey(Staff)
    item = models.ForeignKey(DessertItem)
    plan = models.ForeignKey(WeekdayPlan, related_name='entries')
    limit = models.IntegerField()
    stock = models.IntegerField()
    price = models.FloatField()

    def __unicode__(self):
        return 'Daily plan at day %s of %s' % (self.weekday, self.item)
